package com.shigu.trade.service;

import com.opentae.data.mall.beans.*;
import com.opentae.data.mall.examples.MallOrderExample;
import com.opentae.data.mall.examples.MallOrderLogisticsExample;
import com.opentae.data.mall.examples.MallTradeExample;
import com.opentae.data.mall.interfaces.*;
import com.shigu.MallResponse;
import com.shigu.account.api.VipManagerService;
import com.shigu.account.enums.MoneyRecordType;
import com.shigu.account.enums.VipLevel;
import com.shigu.account.exception.UtilsAccountException;
import com.shigu.account.service.UserAccountService;
import com.shigu.account.vo.BonusVo;
import com.shigu.appVersion.service.VersionService;
import com.shigu.exceptions.WapException;
import com.shigu.paypwd.util.MD5Util;
import com.shigu.postFee.service.PostFeeService;
import com.shigu.trade.enums.*;
import com.shigu.trade.vo.AppWxPayResponse;
import com.shigu.trade.vo.ConfirmTradeResponse;
import com.shigu.trade.vo.PayByWxResponse;
import com.shigu.trade.vo.PostFeeResponse;
import com.shigu.user.service.MallTokenService;
import com.shigu.util.MoneyUtil;

import com.shigu.weixin.enums.WxConfigSource;
import com.shigu.weixin.service.PayApplyService;
import com.shigu.weixin.vo.AppPayVo;
import com.shigu.weixin.vo.JSAPIVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;

import java.util.Date;


@Service
public class TradeService {
    @Autowired
    MallUserAddrMapper mallUserAddrMapper;
    @Autowired
    MallTradeMapper mallTradeMapper;
    @Autowired
    MallOrderMapper mallOrderMapper;
    @Autowired
    MallOrderRecordMapper mallOrderRecordMapper;
    @Autowired
    MallItemMapper mallItemMapper;
    @Autowired
    MallSkuMapper mallSkuMapper;
    @Autowired
    PostFeeService postFeeService;
    @Autowired
    PayApplyService payApplyService;
    @Autowired
    ManagerMallUserMapper managerMallUserMapper;
    @Autowired
    MallOrderLogisticsMapper mallOrderLogisticsMapper;
    @Autowired
    UserAccountService userAccountService;
    @Autowired
    TradeAdminService tradeAdminService;
    @Autowired
    TradeService tradeService;
    @Autowired
    MallTokenService mallTokenService;

    @Resource(name = "vipManagerServiceImpl")
    VipManagerService vipManagerService;
    @Autowired
    UserInviteInfoMapper userInviteInfoMapper;
    @Autowired
    MallBonusMapper mallBonusMapper;
    @Autowired
    VersionService versionService;

    /**
     * @description app下单
     * @author 郭尔
     * @date 2019/1/13 14:12
     */
    public synchronized ConfirmTradeResponse confirmTrade(int num, Long itemId, Long skuId, Long userId, String version, String os) throws WapException {

        Long  rewardId = null;
        ManagerMallUser user = managerMallUserMapper.selectByPrimaryKey(userId);

        UserInviteInfo info = userInviteInfoMapper.selectByPrimaryKey(user);
        //用户等级为boss 不需要往推荐人推
        if (info.getVipLevel() < VipLevel.BOSS.getValue()) {
            rewardId = info.getAgentId();
        }
        String uri = versionService.versionUri(version, os);
        Integer dis = vipManagerService.vipDiscount(userId, uri);
        double discount = MoneyUtil.formatMoneyDouble(Double.valueOf(dis) / 100);//除以100 用于计算
        TradeSource source = TradeSource.APP;

        String tradeCode = confirmTrade(num, itemId, skuId, userId, discount, source.getValue());

        MallTrade trade = mallTradeMapper.selByTradeCode(tradeCode);
        double money = MoneyUtil.divide(trade.getPayMoney(),discount);

        BonusVo vo = vipManagerService.distributeMoney(userId, money,true);
        if (vo != null) {
            trade.setRewardId(rewardId);
            Double reward = vo.getMap().get(rewardId);
            if(reward!=null){
                trade.setReward(reward);
            }
            mallTradeMapper.updateByPrimaryKeySelective(trade);
            distribute(vo,tradeCode,money,num);
        }

        ConfirmTradeResponse response = new ConfirmTradeResponse();
        response.setTradeCode(tradeCode);
        return response.success();
    }

    /**
     * @description 公众号下单
     * @author 郭尔
     * @date 2019-11-11 17:02
     */
    public synchronized ConfirmTradeResponse confirmTrade(int num, Long itemId, Long skuId, Long userId, String sharer) throws WapException {

        Long rewardId = mallTokenService.selUserIdByToken(sharer);
        double discount = 1;
        TradeSource source = TradeSource.GZH;
        String tradeCode = confirmTrade(num, itemId, skuId, userId, discount, source.getValue());

        MallTrade trade = mallTradeMapper.selByTradeCode(tradeCode);

        BonusVo vo = vipManagerService.distributeMoney(userId,trade.getPayMoney() ,false);
        if (vo != null) {
            trade.setRewardId(rewardId);
            Double reward = vo.getMap().get(rewardId);
            if(reward!=null){
                trade.setReward(reward);
            }
            mallTradeMapper.updateByPrimaryKeySelective(trade);
            distribute(vo,tradeCode,trade.getPayMoney(),num);
        }

        ConfirmTradeResponse response = new ConfirmTradeResponse();
        response.setTradeCode(tradeCode);
        return response.success();
    }

    /**
     * @description 下单
     * @author 郭尔
     * @date 2019-11-11 17:06
     */
    public String confirmTrade(int num, Long itemId, Long skuId, Long userId, double discount, int source) throws WapException {
        //清除之前的未确认的订单
        tradeService.clearTrade(userId);
        MallItem item = mallItemMapper.selectByPrimaryKey(itemId);
        if (item == null || !item.getOnsale()) {
            throw new WapException("商品不存在或已下架");
        }
        //商品信息
        String[] imgs = item.getImages().split(",");
        double payMoney = item.getDiscount() * num * discount;

        //插入到表中
        MallTrade trade = new MallTrade();
        MallOrder order = new MallOrder();
        MallOrderRecord record = new MallOrderRecord();

        //初步下订单，没有邮费 total 和 pay 相同
        trade.setPayStatus(TradePayStatus.NOPAY.getValue());
        trade.setSendStatus(TradeSendStatus.NOSEND.getValue());
        trade.setTradeStatus(TradeStatus.INITAIL.getValue());
        trade.setBuyerId(userId);
        trade.setTotalMoney(payMoney);
        trade.setPayMoney(payMoney);
        trade.setSource(source);

        mallTradeMapper.insertSelective(trade);
        String tradeCode = praseTradeCode(trade.getTid());
        trade.setTradeCode(tradeCode);

        mallTradeMapper.updateByPrimaryKeySelective(trade);

        order.setTid(trade.getTid());
        order.setBuyerId(userId);
        order.setTradeCode(tradeCode);
        order.setSkuId(skuId);
        order.setTitle(item.getTitle());
        order.setSku(mallSkuMapper.selectByPrimaryKey(skuId).getSkuValue());
        order.setImgUrl(imgs[0]);
        order.setPrice(item.getPrice());
        order.setDiscount(item.getDiscount());
        order.setPayMoney(payMoney);
        order.setPostFee(0.00);
        order.setNum(num);
        order.setItemId(itemId);
        mallOrderMapper.insertSelective(order);

        record.setTid(trade.getTid());
        record.setTradeCode(tradeCode);
        record.setChangeTime(new Date());
        record.setToStatus(RecordToStatus.INITAL.getValue());
        mallOrderRecordMapper.insertSelective(record);

        return tradeCode;
    }


    /**
     * @description 插入到分润表
     * @author 郭尔
     * @date 2019-11-11 15:40
     */
    private void distribute(BonusVo vo, String tradeCode, Double payMoney, int num) {
        MallBonus bonus = new MallBonus();
        bonus.setPayMoney(payMoney);
        bonus.setTradeCode(tradeCode);
        bonus.setNum(num);

        bonus.setStaff(vo.getStaff());
        bonus.setStaffBonus(vo.getStaffBouns());
        bonus.setOwner(vo.getOwner());
        bonus.setOwnerBonus(vo.getOwnerBouns());
        bonus.setBoss(vo.getBoss());
        bonus.setBossBonus(vo.getBossBouns());
        bonus.setStatus(false);
        mallBonusMapper.insertSelective(bonus);

    }

    /**
     * @description tid 生成tradeCode
     * @author 郭尔
     * @date 2019/1/13 14:54
     */
    private String praseTradeCode(Long tid) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        DecimalFormat df = new DecimalFormat("000000000");
        return sdf.format(new Date()) + df.format(tid);
    }

    /**
     * @description 订单的运费
     * @author 郭尔
     * @date 2019/1/13 15:02
     */
    public PostFeeResponse tradePostFee(String tradeCode, Long addressId) {
        PostFeeResponse response = new PostFeeResponse();
        if (addressId == null) {
            response.setPostFee("0");
        } else {
            MallOrder order = mallOrderMapper.selectOrderByTradeCode(tradeCode);
            MallItem item = mallItemMapper.selectByPrimaryKey(order.getItemId());
            int weight = item.getWeight() == null ? 0 : item.getWeight();
            double fee = postFeeService.postFee(weight, item.getFeeId(), order.getNum(), mallUserAddrMapper.getProvId(addressId));
            response.setPostFee(MoneyUtil.formatPriceMoney(fee));
        }
        return response.success();
    }


    /**
     * @description 确认收货
     * @author 郭尔
     * @date 2019/1/13 16:49
     */
    public synchronized MallResponse receiveTrade(String tradeCode) {
        MallTrade trade = mallTradeMapper.selByTradeCode(tradeCode);
        if (trade.getSendStatus() == TradeSendStatus.RECEIVE.getValue()) {
            return new MallResponse().success();
        }
        trade.setTradeStatus(TradeStatus.COMPLETED.getValue());
        trade.setSendStatus(TradeSendStatus.RECEIVE.getValue());

        MallOrderRecord record = new MallOrderRecord();
        record.setChangeTime(new Date());
        record.setTid(trade.getTid());
        record.setTradeCode(tradeCode);
        record.setToStatus(RecordToStatus.RECEIVE.getValue());

        mallTradeMapper.updateByPrimaryKeySelective(trade);
        mallOrderRecordMapper.insertSelective(record);

        MallOrder order = mallOrderMapper.selectOrderByTradeCode(tradeCode);
        MallItem item = mallItemMapper.selectByPrimaryKey(order.getItemId());
        item.setSales(item.getSales() + order.getNum());
        mallItemMapper.updateByPrimaryKeySelective(item);

//        ManagerMallUser mallUser = managerMallUserMapper.selectByPrimaryKey(trade.getBuyerId());
//        mallUser.setHaveCost(mallUser.getHaveCost()+trade.getTotalMoney());
//        managerMallUserMapper.updateByPrimaryKeySelective(mallUser);

        return new MallResponse().success();
    }

    /**
     * @description 微信付款
     * @author 郭尔
     * @date 2019/1/15 15:11
     */
    public PayByWxResponse goPayByWx(String tradeCode, Long userId) throws Exception {
        MallTrade trade = mallTradeMapper.selByTradeCode(tradeCode);
        JSAPIVo vo = payApplyService.applyWxPay(userId, trade.getTotalMoney(), tradeCode, WxConfigSource.XCX);
        PayByWxResponse response = new PayByWxResponse();
        response.setAppId(vo.getAppId());
        response.setTimeStamp(vo.getTimeStamp());
        response.setNonceStr(vo.getNonceStr());
        response.setPrepayId(vo.getPrepayId());
        response.setPaySign(vo.getPaySign());
        return response.success();
    }

    /**
     * @description 余额支付
     * @author 郭尔
     * @date 2019/1/15 15:41
     */
    public synchronized MallResponse goPayByWallet(String tradeCode, Long userId, String payPwd) throws WapException, UtilsAccountException {
        MallTrade trade = mallTradeMapper.selByTradeCode(tradeCode);
        ManagerMallUser user = managerMallUserMapper.selectByPrimaryKey(userId);
        if (!MD5Util.md5(payPwd).equals(user.getPayPwd())) {
            throw new WapException("支付密码不正确");
        }
        userAccountService.reduceMoney(userId, trade.getTotalMoney(), MoneyRecordType.pay.getText() + ",订单号:" + tradeCode);//非财神用
        tradeAdminService.dowithTrade(tradeCode, true, PayWay.WALLET);

        return new MallResponse().success();
    }


    /**
     * @description 抵用券支付
     * @author 郭尔
     * @date 2019/1/15 15:41
     */
    public synchronized MallResponse goPayByVoucher(String tradeCode, Long userId, String payPwd) throws WapException, UtilsAccountException {
        MallTrade trade = mallTradeMapper.selByTradeCode(tradeCode);
        ManagerMallUser user = managerMallUserMapper.selectByPrimaryKey(userId);
        if (!MD5Util.md5(payPwd).equals(user.getPayPwd())) {
            throw new WapException("支付密码不正确");
        }
        userAccountService.reduceVoucher(userId, trade.getTotalMoney(), MoneyRecordType.voucher.getText() + ",订单号:" + tradeCode);//非财神用
        tradeAdminService.dowithTrade(tradeCode, true, PayWay.VOUCHER);
        return new MallResponse().success();
    }

    /**
     * @description 完善订单信息
     * @author 郭尔
     * @date 2019/1/16 10:52
     */
    public MallResponse compeleteOrderInfo(Long addressId, String tradeCode, Long userId) {
        MallUserAddr addr = mallUserAddrMapper.selectByPrimaryKey(addressId);
        MallTrade trade = mallTradeMapper.selByTradeCode(tradeCode);
        MallOrder order = mallOrderMapper.selectOrderByTradeCode(tradeCode);
        MallItem item = mallItemMapper.selectByPrimaryKey(order.getItemId());

        int weight = item.getWeight() == null ? 0 : item.getWeight();
        double postFee = postFeeService.postFee(weight, item.getFeeId(), order.getNum(), addr.getProvId());//获取运费
        order.setPostFee(postFee);
        order.setPayMoney(order.getPayMoney());

        trade.setTradeStatus(TradeStatus.COMFIRM.getValue());
        trade.setTotalMoney(trade.getPayMoney() + postFee);
        trade.setCreateTime(new Date());//完善后才算
        //先清除原先订单的地址信息
        MallOrderLogisticsExample example = new MallOrderLogisticsExample();
        example.createCriteria().andTradeCodeEqualTo(tradeCode);
        mallOrderLogisticsMapper.deleteByExample(example);

        MallOrderLogistics logistics = new MallOrderLogistics();
        logistics.setReceiveTelephone(addr.getReceiveTelephone());
        logistics.setReceiveName(addr.getReceiveName());
        logistics.setAddressDetail(addr.getAddressDetail());
        logistics.setTradeCode(tradeCode);
        logistics.setTid(trade.getTid());
        logistics.setProvName(addr.getProvName());
        logistics.setAreaName(addr.getAreaName());
        logistics.setCityName(addr.getCityName());
        logistics.setBuyerId(userId);

        mallOrderLogisticsMapper.insertSelective(logistics);
        mallOrderMapper.updateByPrimaryKeySelective(order);
        mallTradeMapper.updateByPrimaryKeySelective(trade);

        return new MallResponse().success();
    }

    /**
     * @description 删除订单
     * @author 郭尔
     * @date 2019/1/15 17:01
     */
    public MallResponse giveUpTrade(String tradeCode) {
        Long tid = mallTradeMapper.selTidByTradeCode(tradeCode);
        MallOrderExample orderExample = new MallOrderExample();
        orderExample.createCriteria().andTidEqualTo(tid).andTradeCodeEqualTo(tradeCode);

        MallOrderLogisticsExample example = new MallOrderLogisticsExample();
        example.createCriteria().andTidEqualTo(tid).andTradeCodeEqualTo(tradeCode);

        mallTradeMapper.deleteByPrimaryKey(tid);
        mallOrderLogisticsMapper.deleteByExample(example);
        mallOrderMapper.deleteByExample(orderExample);
        return new MallResponse().success();
    }

    /**
     * @description 清除用户未确认的订单
     * @author 郭尔
     * @date 2019/1/24 14:23
     */
    private void clearTrade(Long userId) {
        //该用户未选择地址的订单
        MallTradeExample example = new MallTradeExample();
        example.createCriteria().andBuyerIdEqualTo(userId).andTradeStatusEqualTo(TradeStatus.INITAIL.getValue());
        mallTradeMapper.deleteByExample(example);

        mallOrderMapper.clearOrder(userId);
    }

    /**
     * @description 微信付款
     * @author 郭尔
     * @date 2019/1/15 15:11
     */
    public AppWxPayResponse appWxPay(String tradeCode, Long userId) throws Exception {
        MallTrade trade = mallTradeMapper.selByTradeCode(tradeCode);
        AppPayVo vo = payApplyService.appWxPay(userId, trade.getTotalMoney() + "", tradeCode);
        AppWxPayResponse response = new AppWxPayResponse();
        response.setPartnerId(vo.getPartnerId());
        response.setAppId(vo.getAppId());
        response.setTimeStamp(vo.getTimeStamp());
        response.setNonceStr(vo.getNonceStr());
        response.setPrepayId(vo.getPrepayId());
        response.setSign(vo.getSign());
        return response.success();
    }
}
